package xyz.labmem.service

import cn.hutool.core.lang.Console
import cn.hutool.core.util.ZipUtil
import cn.hutool.http.ContentType
import cn.hutool.http.HttpUtil
import cn.hutool.http.server.SimpleServer
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import javafx.application.Platform
import org.smartboot.http.server.HttpBootstrap
import org.smartboot.http.server.WebSocketRequest
import org.smartboot.http.server.WebSocketResponse
import org.smartboot.http.server.handler.WebSocketDefaultHandler
import org.smartboot.http.server.handler.WebSocketRouteHandler
import org.smartboot.http.server.impl.WebSocketRequestImpl
import org.smartboot.http.server.impl.WebSocketResponseImpl
import xyz.labmem.PackageRun
import xyz.labmem.config.BrowserReptileConfig
import xyz.labmem.config.BrowserReptileTask
import xyz.labmem.controller.BrowserReptileController
import xyz.labmem.core.util.getJarFile
import xyz.labmem.core.util.getResourceFile
import xyz.labmem.result.ResultUtil
import java.io.File
import kotlin.collections.ArrayList
import kotlin.collections.HashMap


/**
 * @Author lty
 * @Date 2021/9/28 16:35
 */
class BrowserReptileSimpleServer(controller: BrowserReptileController) {


    var root: String
    private val base = controller

    private var contentSession: WebSocketResponseImpl? = null

    init {
        Console.log(this::class.getJarFile().path)
        root = if (File(this::class.getJarFile().path).isDirectory) {
            this::class.getJarFile().path
        } else {
            //获取htmlzip解压到temp
            val htmlZip = getResourceFile(PackageRun.htmlZipPath).stream
            ZipUtil.unzip(htmlZip, File(PackageRun.staticTempPath), null)
            PackageRun.staticTempPath
        }
    }

    fun create(port: Int): SimpleServer {
        return HttpUtil.createServer(port)
            .addAction("${base.API_PREFIX}/getDeploy") { q, p ->
                p.write(JSON.toJSONString(BrowserReptileConfig), ContentType.JSON.toString())
            }
            .setRoot(root)
    }

    /**
     * 使用websocket 实现页面回调
     */
    fun socket(port: Int) {
        val bootstrap = HttpBootstrap()
        val routeHandle = WebSocketRouteHandler()

        routeHandle.route("/content", object : WebSocketDefaultHandler() {
            override fun onHandShake(request: WebSocketRequest, response: WebSocketResponse) {
                contentSession = (request as WebSocketRequestImpl).response
                super.onHandShake(request, response)
            }
        })
        bootstrap.webSocketHandler(routeHandle)
        bootstrap.configuration().readBufferSize(2048)
        bootstrap.setPort(port).start()
    }

    fun socketSend(data: String) {
        contentSession?.let {
            it.sendTextMessage(data)
            it.flush()
        }
    }

    fun socketSendMethod(Method: String) {
        socketSend(Method, null)
    }

    fun socketSend(method: String, data: Any?) {
        socketSend(JSONObject().apply {
            put("method", method)
            data?.let { put("data", it) }
        }.toJSONString())
    }

    //通讯方法

    fun getTaskList() {
        val data = JSONArray()
        base.reptile.getTask()?.forEach { t ->
            data.add(t.name ?: "")
        }
        socketSend("getTaskList", data)
    }

    fun getTask(index: Int) {
        base.reptile.getTask()?.let { it ->
            it.getOrNull(index)?.let { t ->
                socketSend("getTask_back", ResultUtil.success(JSONObject().apply {
                    put("data", t)
                    put("index", index)
                }))
                return
            }
        }
        socketSend("getTask_back", ResultUtil.failedMessage("未找到此任务"))
    }

    fun saveTask(req: String) {
        try {
            val task = JSON.toJavaObject(JSON.parseObject(req), BrowserReptileTask::class.java)
            base.reptile.saveTask(task)
            socketSend("save_back", ResultUtil.successMessage("保存成功!"))
        } catch (e: Exception) {
            e.printStackTrace()
            socketSend("save_back", ResultUtil.failedMessage("保存失败【${e.message}】"))
        }
    }

    fun editTask(req: String) {
        try {
            val data = JSON.parseObject(req)
            val index = data.getIntValue("index")
            val task = JSON.toJavaObject(data.getJSONObject("data"), BrowserReptileTask::class.java)
            base.reptile.saveTask(task, index)
            socketSend("save_back", ResultUtil.successMessage("修改成功！"))
        } catch (e: Exception) {
            e.printStackTrace()
            socketSend("save_back", ResultUtil.failedMessage("修改失败【${e.message}】"))
        }
    }

    fun delTask(index: Int) {
        Platform.runLater {
            base.alert.apply {
                title = "警告"
                message = "是否要删除该任务？"
                setCancelBtn("取消")
                setSureBtn("确定") {
                    base.loading.apply {
                        base.view.updateStatus(-1.0, "正在删除任务..")
                        getMasker().text = "正在删除任务.."
                        show()
                    }
                    base.reptile.getTask()?.let { it ->
                        it.getOrNull(index)?.let { _ ->
                            it.removeAt(index)
                            base.reptile.saveTask(it)
                            getTaskList()
                            base.loading.hide()
                            base.view.doneStatus()
                        }
                    }
                }
                create()
            }
        }
    }

    fun selectFilePath(name: String) {
        Platform.runLater {
            base.fileChooser.showOpenDialog(base.stage)?.let {
                socketSend(
                    "deploy_file_back", ResultUtil.success(JSONObject().apply {
                        put("filePath", it.path)
                        put("name", name)
                    })
                )
            }
        }
    }

    fun saveDeploy(data: String) {
        try {
            JSON.parseObject(data).apply {
                BrowserReptileConfig.driverDir = getString("driverDir")
                BrowserReptileConfig.chromePath = getString("chromePath")
            }
            BrowserReptileConfig.write()
            BrowserReptileConfig.refreshDriver()
            socketSend("saveDeploy_back", ResultUtil.success())
        } catch (e: Exception) {
            BrowserReptileConfig.readConfig()
            socketSend("saveDeploy_back", ResultUtil.failedMessage("保存配置失败【${e.message}】"))
        }
    }

    fun runTask(data: String) {
        try {
            val tasks = base.reptile.getTask()
            if (tasks != null && tasks.size > 0) {
                val selected = HashMap<Int, BrowserReptileTask>()
                val res = ArrayList<HashMap<String, Any>>()
                JSON.parseArray(data).forEach {
                    val i = it.toString().toInt()
                    selected[i] = tasks[i]
                    res.add(HashMap<String, Any>().apply {
                        put("index", i)
                        put("name", tasks[i].name!!)
                    })
                }
                base.taskThreadRun(selected)
                socketSend("runTask_back", ResultUtil.success(res))
            } else
                socketSend("runTask_back", ResultUtil.failedMessage("任务读取失败"))
        } catch (e: Exception) {
            e.printStackTrace()
            socketSend("runTask_back", ResultUtil.failedMessage("任务运行失败【${e.message}】"))
        }
    }


    fun showLog(data: String) {
        socketSend("log", data)
    }

}